package net.sourceforge.jweb.jstl.easyui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.jsp.tagext.BodyTagSupport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sourceforge.jweb.json.JSONException;
import net.sourceforge.jweb.json.JSONObject;
import net.sourceforge.jweb.jstl.JsSupport;
import net.sourceforge.jweb.jstl.json.JsonEntity;

public abstract class BaseEasyuiTag extends BodyTagSupport implements JsSupport, Constants {
	private static final long serialVersionUID = 1L;
	private final static Logger LOGGER = LoggerFactory.getLogger(BaseEasyuiTag.class);
	protected Map<String, Object> properties = new LinkedHashMap<String, Object>();
	protected JsonEntity entity;

	@SuppressWarnings("unchecked")
	protected void addLazyPageContent(final String content) {
		List<String> lazyContentList = new ArrayList<>();
		Object obj = this.pageContext.getRequest().getAttribute(KEY_LAZY_WRITE);
		if (obj != null) {
			lazyContentList = (List<String>) obj;
		} else {
			this.pageContext.getRequest().setAttribute(KEY_LAZY_WRITE, lazyContentList);
		}
		lazyContentList.add(content);
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("added lazy js");
		}
	}

	/***
	 * 深度归并两个map， 把source合并到target
	 * 
	 * @param properties
	 * @param columnAttrMap
	 */
	@SuppressWarnings("unchecked")
	protected void mergeMap(Map<String, Object> source, Map<String, Object> target) {
		for (Entry<String, Object> newEntry : source.entrySet()) {
			String newKey = newEntry.getKey();
			Object newValue = newEntry.getValue();
			Object oldValue = target.get(newKey);
			if (oldValue == null) {// it is new entry, just put to map
				target.put(newKey, newValue);
				LOGGER.debug("key {} is new, just merge to map", newKey);
			} else {
				if ((newValue instanceof Map) && (oldValue instanceof Map)) {
					mergeMap((Map<String, Object>) newValue, (Map<String, Object>) oldValue);
				}
				// 数组不考虑深度合并，会直接覆盖
				else {
					target.put(newKey, newValue);
					LOGGER.info("You are overriding key={} with different data type", newKey);
				}
			}
		}
	}

	@Override
	public void addJsonEntity(JsonEntity entity) {
		this.entity = entity;
	}

	// 把json对象合并到map中，注意级别,jsonObject本身作为了一个key-valuemap
	protected void mergeJsonObject(Map<String, Object> map, JSONObject jsonObject) throws JSONException {
		if (!jsonObject.quotoNameSet()) {
			jsonObject.setQuotoName(false);// not quoto name by default
		}
		
		if(jsonObject.isAsPrimary()&&jsonObject.length()==1) {
			String key=jsonObject.keys().next();
			map.put(key, jsonObject.get(key).toString());
			return ;
		}

		String key = jsonObject.getName();
		Object oldValue = map.get(key);

		if (oldValue != null) {// equals to map
			if (oldValue instanceof Map) {
				Map<String, Object> castedOldValue = (Map<String, Object>) oldValue;
				Iterator ite = jsonObject.keys();
				while (ite.hasNext()) {
					String valueKey = ite.next().toString();
					Object jsonValue = jsonObject.get(valueKey);
					if (castedOldValue.containsKey(valueKey)) {
						Object mapValue = map.get(valueKey);
						if (mapValue instanceof Map && jsonValue instanceof JSONObject) {
							mergeJsonObject((Map<String, Object>) mapValue, (JSONObject) jsonValue);
						} else {
							LOGGER.debug("override existing entry with whold JSON string");
							castedOldValue.put(valueKey, jsonValue.toString());
						}
					} else {
						// new entry
						castedOldValue.put(valueKey, jsonValue.toString());
					}
				}
			} else {
				LOGGER.debug("override existing entry with whold JSON string");
				map.put(key, jsonObject.toString());
			}
		} else {// 检查是否需要quoto
			map.put(key, jsonObject.toString());
		}
	}
}
